package com.nulldev.util.java.extendedUI.cSwing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.extendedUI.cSwing.Fonts.IcoMoon;
import com.nulldev.util.java.extendedUI.cSwing.resizing.BackgroundComponentDragger;
import com.nulldev.util.java.extendedUI.cSwing.resizing.ComponentBorderDragger;
import com.nulldev.util.java.extendedUI.cSwing.resizing.FrameComponent;
import com.nulldev.util.java.swing.canvas.SmoothCanvas;
import com.nulldev.util.java.swing.extSwing.PolyBorder;
import com.nulldev.util.java.swing.extSwing.RoundedBorder;
import com.nulldev.util.java.swing.font.FontManager;

import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.ActionEvent;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;

public class cSwing extends JFrame implements MouseMotionListener, MouseListener {

	private JPanel contentPane;
	private JLabel lblNewWindow;
	private JButton button_1;
	
	private boolean useNativeDecorations = false;

	/**
	 * Launch the application.
	 */
	public static void main() {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					cSwing frame = new cSwing();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public cSwing() {
		super.setTitle("New Window");
		//super.addMouseListener(this);
		//super.addMouseMotionListener(this);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		setUndecorated(true);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		contentPane.setLayout(new BorderLayout(0, 0));
		super.setContentPane(contentPane);
		
		JPanel panel = new JPanel();
		contentPane.add(panel, BorderLayout.NORTH);
		panel.setLayout(new BorderLayout(0, 0));
		
		panel_1 = new JPanel() {
			@Override
			public void setBorder(final Border border) {
				super.setBorder(new PolyBorder(Color.GRAY));
			}
		};
		panel_1.setBorder(new PolyBorder(Color.GRAY));
		panel.add(panel_1, BorderLayout.CENTER);
		panel_1.setLayout(new BorderLayout(0, 0));
		
		lblNewWindow = new JLabel("New Window");
		lblNewWindow.setHorizontalAlignment(SwingConstants.CENTER);
		panel_1.add(lblNewWindow, BorderLayout.CENTER);
		
		JPanel panel_2 = new JPanel(new FlowLayout(FlowLayout.TRAILING, 0, 0));
		panel_1.add(panel_2, BorderLayout.EAST);
		
		JButton button = new JButton("\uea0b") {
			@Override
			public void setFont(final Font font) {
				super.setFont(IcoMoon.getCached(12));
			}
		};
		button.setContentAreaFilled(false);
		button.setBorder(new RoundedBorder(5));
		button.setFocusable(false);
		button.setFont(IcoMoon.getCached(12));
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cSwing.this.setExtendedState(cSwing.this.ICONIFIED);
			}
		});
		panel_2.add(button);
		
		button_1 = new JButton("\ue98b") {
			@Override
			public void setFont(final Font font) {
				super.setFont(IcoMoon.getCached(12));
			}
		};
		button_1.setContentAreaFilled(false);
		button_1.setBorder(new RoundedBorder(5));
		button_1.setFont(IcoMoon.getCached(12));
		button_1.setFocusable(false);
		button_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (cSwing.this.isResizable()) {
					if (cSwing.this.getExtendedState() == MAXIMIZED_BOTH) {
						cSwing.this.setExtendedState(cSwing.this.NORMAL);
						cSwing.this.getMaxMinButton().setText("\ue98b");
					}else {
						cSwing.this.setExtendedState(cSwing.this.getExtendedState() | cSwing.this.MAXIMIZED_BOTH);
						cSwing.this.getMaxMinButton().setText("\ue98c");
					}
				}
			}
		});
		panel_2.add(button_1);
		
		JButton btnX = new JButton("\uea0f") {
			@Override
			public void setFont(final Font font) {
				super.setFont(IcoMoon.getCached(12));
			}
		};
		btnX.setFocusable(false);
		btnX.setContentAreaFilled(false);
		btnX.setBorder(new RoundedBorder(5));
		btnX.setFont(IcoMoon.getCached(12));
		btnX.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (cSwing.this.getDefaultCloseOperation() != cSwing.DO_NOTHING_ON_CLOSE) {
					for (final Component c : panel_1.getComponents()) {
						if (c instanceof SmoothCanvas) {
							((SmoothCanvas)c).dispose();
						}else {
							continue;
						}
					}
					cSwing.this.setVisible(false);
					cSwing.this.dispose();
				}
				if (cSwing.this.getDefaultCloseOperation() == cSwing.EXIT_ON_CLOSE) {
					JVMUtil.exit();
				}
			}
		});
		panel_2.add(btnX);
		
		JPanel panel_3 = new JPanel();
		panel_1.add(panel_3, BorderLayout.WEST);
		panel_3.setLayout(new BorderLayout(0, 0));
		
		JLabel label = new JLabel();
		panel_3.add(label, BorderLayout.WEST);
		
		if (this.getIconImage() != null) {
			label.setIcon(new ImageIcon(this.getIconImage()));
		}
		
		final FrameComponent fc = new FrameComponent(new Insets(5, 5, 5, 5));
		setFrameController(fc);
		setFrameSizeController(fc, this.getTopElement());
		setBackgroundPanelController(this.contentPane);
	}

	@Override
	public void setContentPane(final Container cont) {
		if (this.contentPane == null) {
			return;
		}
		this.contentPane.add(cont);
	}
	
	@Override
	public void setTitle(final String title) {
		if (title == null) {
			this.setTitle("");
			return;
		}
		this.getTitleLabel().setText(title);
		super.setTitle(title);
	}
	
	@Override
	public Component add(final Component comp) {
		this.contentPane.add(comp);
		return comp;
	}
	
	protected JLabel getTitleLabel() {
		return lblNewWindow;
	}
	
	protected JButton getMaxMinButton() {
		return button_1;
	}
	
	@Override
	public void mouseDragged(MouseEvent e) {
		if ((e.getY() > 0 && e.getY() < this.getTopElement().getHeight())) {
			//setLocation((int) e.getXOnScreen() - 20, (int) e.getYOnScreen());
            int thisX = this.getLocation().x;
            int thisY = this.getLocation().y;

            // Determine how much the mouse moved since the initial click
            int xMoved = (thisX + e.getX()) - (thisX + initialClick.x);
            int yMoved = (thisY + e.getY()) - (thisY + initialClick.y);

            // Move window to this position
            int X = thisX + xMoved;
            int Y = thisY + yMoved;
            this.setLocation(X, Y);
		}
	}
	
	protected Point initialClick;
	private JPanel panel_1;

	@Override
	public void mouseMoved(MouseEvent e) {
	}
	
	protected JPanel getTopElement() {
		return panel_1;
	}

	@Override
	public void mouseClicked(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
		this.initialClick = e.getPoint();
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}
	
	public boolean usesNativeDecorations() {
		return this.useNativeDecorations;
	}
	
	public void setNativeDecorations(final boolean state) {
		if (!this.useNativeDecorations && !state) {
			return;
		}
		this.setVisible(false);
		dispose();
		this.useNativeDecorations = state;
		this.setUndecorated(!state);
		this.getTopElement().setVisible(!state);
		this.setVisible(true);
	}
	
	private void setFrameSizeController(FrameComponent frame, JPanel panel) {
		this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
            	if (cSwing.this.useNativeDecorations) {
            		return;
            	}
            	if (e.getComponent() instanceof JFrame) {
            		Dimension sizeIn = ((JFrame) e.getComponent()).getContentPane().getSize();
                    frame.setSize(sizeIn);
                    panel.setSize(sizeIn);
            	}else {
            		Dimension sizeIn = ((JPanel) e.getComponent()).getSize();
                    frame.setSize(sizeIn);
                    panel.setSize(sizeIn);
            	}
                
            }
        });
    }

    private void setFrameController(FrameComponent frame) {
        ComponentBorderDragger controller = new ComponentBorderDragger(this.getTopElement(),
                new Insets(5, 5, 5, 5), new Dimension(10, 10)) {

					@Override
					public boolean skip() {
						return cSwing.this.useNativeDecorations;
					}
        	
        };
        frame.addMouseMotionListener(controller);
    }

    private void setBackgroundPanelController(JPanel panel) {
        panel.addMouseMotionListener(new BackgroundComponentDragger(this) {

			@Override
			public boolean skip() {
				return cSwing.this.useNativeDecorations;
			}
        	
        });
    }
}
